
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <libmemcached/memcached.h>

#include "Debug.h"
#include "Helper.h"
#include "configParser.h"
 
using namespace std;
Helper * Helper::_instance = NULL;

Helper::Helper() 
{
        m_sConfFile = "";
        m_gets = 0;
        m_sets = 0;
}

Helper::~Helper()
{
}

Helper * Helper::Instance(const char *confFile)
{
	if (NULL == _instance) 
	{
		_instance = new Helper();
		if ( !_instance->Startup(confFile) ) {
			delete _instance; 
			_instance = NULL;
		}
	}
	return _instance;
}

void Helper::Release(bool bForce)
{
	if (_instance) 
	{
		if(bForce)
		{
			delete _instance; 
			_instance = NULL;
		}
	}
}

bool  Helper::Startup(const char *confFile)
{
	if(confFile != NULL)
		m_sConfFile  = confFile;
	if(m_sConfFile.length() < 1)
	{
		ERRO<<": no helper.conf be given!"<<endl;
		return false;
	}
	struct stat st;
	if (lstat(confFile, &st) != 0)
	{
		ERRO<<":"<<confFile<<" is not exist!"<<endl;
		return false;
	}

	configParser cfg;
	map <string, string > g_Confs;
	g_Confs = cfg.Parser(confFile);
	if(g_Confs.size() <= 0)
	{
		cerr<<"error to explain conf :"<< confFile <<endl;
		return false;
	}
       
        map <string , string >::iterator iter;
        for(iter=g_Confs.begin(); iter != g_Confs.end(); iter++)
        {
             cout<< iter->first.c_str()<<"="<<iter->second.c_str()<<endl;
        }



        int itype = 0;
	if( g_Confs.find("connection_type") != g_Confs.end())
	{
		string stype  = g_Confs["connection_type"];
                itype = atoi(stype.c_str());
	}

        if(itype<0 || itype > 3)
        {
             ERRO<<"ERROR: connection_type = "<< itype <<endl;
             return false;
	}  

	m_izWindow = m_ipWindow = 0; 
	if( g_Confs.find("auto_restart") != g_Confs.end())
	{
		string st  = g_Confs["auto_restart"];
		size_t idx = st.find('/', 0);
		if(idx>0 && idx < st.length())
		{
			string sw = st.substr(0, idx);
			string bw = st.substr(idx + 1, st.length()- idx -1);
                        m_izWindow = atoi(sw.c_str());
                        m_ipWindow = atoi(bw.c_str());
                        if(m_ipWindow < m_izWindow)
                             m_ipWindow = 0;
                        DEBUG4("zWindow = ",m_izWindow, "; pWindows = ", m_ipWindow);
		}
	}

	return true;
}

int Helper :: Timer(long time, int gap)
{
	if(m_ipWindow > 0 && m_izWindow < m_ipWindow)
	{
             int sw = time/gap;
             if(m_izWindow == sw%m_ipWindow)
             {
                  INFO <<"it's time to restart now = "<< time  <<endl; 
             }
	}
        return 0;
}

int Helper::Update(const char *key, int klen, int flags, time_t expire, const char *data, int dlen)
{

 m_sets++;
 return 0;
}

int Helper :: Process( map <int, string > &keys, conn *c)
{
        m_gets ++;
sleep(60);
        int i = keys.size();
        int used = 0;
        for(int j = 1; j< i; j++)
        used +=  sprintf(c->wcurr+used , "%d = Hello,%ld",j, time(NULL)+j );
        c->wbytes += used;
        return 0;
}

int Helper :: Process(const char *cmd, conn *c)
{
        c->wbytes +=  sprintf(c->wcurr, "Hello,%ld",time(NULL));
        m_gets ++;
        return 0;
}
int Helper :: Check( void *args )
{
        int *port = (int *)args; 
DEBUG1(" begin to Check!");
	memcached_st * memc = memcached_create(NULL);
	memcached_return rc = MEMCACHED_SUCCESS;
	rc = memcached_server_add(memc,(char *)"127.0.0.1",(unsigned int)(*port));
	if (rc != MEMCACHED_SUCCESS){
		perror("Connect to memcache server");
		memcached_free( memc );
                return 0;
	}
	memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 1);
	memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, 1);
	memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 0);
        size_t vlen;
        uint32_t flag;
	char *retval = memcached_get(memc,"stat", 4, &vlen, &flag, &rc);
	if (rc == MEMCACHED_SUCCESS){
		if (retval != NULL){
                        cout<< retval << endl;
			free(retval);
		}
	}
	if (rc != MEMCACHED_SUCCESS)
	{
		printf("Failure to communicate with servers (%s)\n", memcached_strerror(memc, rc));
		for(int i =0; i< 3; i++)
		{
                        usleep(100);
			retval = memcached_get(memc, "stat", 4, &vlen, &flag, &rc);
			if(rc == MEMCACHED_SUCCESS){
                                cout<<retval << endl;
				free(retval);
				break;
			}
		}
		if(rc != MEMCACHED_SUCCESS){
			memcached_free(memc);
                        exit(1);
			//abort();
		}
	}
       	memcached_free( memc );
DEBUG1("end Check!");
	return 0;
}

char * Helper :: Stats(char *ext_stats)
{
	string status;
	char hostname[128];
	gethostname(hostname, sizeof(hostname)) ;
	status.append("STAT server ");
	status.append(hostname);
	status.append("\r\nSTAT gets ");
        int len = sprintf(hostname, "%ld\r\n", m_gets);
        status.append(hostname, len);

	status.append("STAT sets ");
        len = sprintf(hostname, "%ld\r\n", m_sets);
	status.append(hostname, len);
	if(ext_stats != NULL)
		status.append(ext_stats);
	return (char *)status.c_str();
}


